﻿#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//常见动态内存的错误
// 
// 对空指针的解引用
//int main()
//{
//	int* p = (int*)malloc(40);
//	//要进行判断是否为空指针
//	//在使用时要进行判断
//
//	if (p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		*(p + i) = i;
//	}
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", *(p + i));
//	}
//
//
//	return 0;
//}


//对动态内存的越界访问
//int main()
//{
//	int* p = (int*)malloc(40);//十个整形的数组
//
//	int i = 0;
//	//产生越界访问了，程序会崩溃
//	for (i = 0; i <= 10; i++)
//	{
//		*(p + i) = i;
//		//	p[i] = i;
//	}
//
//
//	return 0;
//}



//对非动态内存的free释放--错误
//int main()
//{
//	int* p = malloc(40);
//	if (p == NULL)
//	{
//		return 1;
//	}
//
//	int arr[5] = { 0 };
//	p = arr;
//
//	free(p);//这是对非动态内存的释放
//	p = NULL;
//
//	return 0;
//}



//使用free释放⼀块动态开辟内存的⼀部分
//int main()
//{
//	int* p = (int*)malloc(40);
//
//	if (p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//
//	//使用
//
//	int i = 0;
//	for (i = 0; i < 5; i++)
//	{
//		//这样会使p指针移动，动态分配的内存起始地址就会找不到
//		*p = i;
//		p++;
//	}
//	
//	//释放
//	//这样释放就只会释放动态内存的一部分
//	free(p);
//	p = NULL;
//
//	return 0;
//}



//对同⼀块动态内存多次释放
//int main()
//{
//	int* p = (int*)malloc(40);
//
//	if (p == NULL)
//	{
//		return 1;
//	}
//	//使用
//
//
//	//释放
//	//多次free同一块内存，程序也会崩溃
//	free(p);
//	p = NULL;
//	//将p置为空指针的话，可以再次free。
//	//....
//	free(p);
//	
//	return 0;
//}


// 动态开辟内存忘记释放（内存泄漏）
//int* test()
//{
//	int* p = (int*)malloc(40);
//
//	if (p == NULL)
//	{
//		return 1;
//	}
//	//使用
//
//	//while (1)//死循环
//	//	;
//	////不释放的话，内存会泄露，也就是忘记释放
//
//
//	return p;
//}
//
//int main()
//{
//	//test();
//	int* p = test();
//	//程序返回之后，无法释放
//	//解决方法 把p的地址带回来
//	//         在函数内就释放
//
//	free(p);
//	p = NULL;
//	return 0;
//}
//



//void test()
//{
//	int* p = (int*)malloc(40);
//
//	if (p == NULL)
//	{
//		return 1;
//	}
//	//使用
//	if (1)
//	{
//		return;
//	}
//	//这样提前return 也会是无法释放
//	free(p);
//	p = NULL;
//
//}
//
//int main()
//{
//	test();
//
//	return 0;
//}


//笔试题1
//void GetMemory(char* p)
//{
//	p = (char*)malloc(100);
//}
//改正1
//char* GetMemory()
//{
//	char* p = (char*)malloc(100);
//	if(p == NULL)
// {
//		perror("malloc");
// }
//
//	return p;
//}
//void Test(void)
//{
//	char* str = NULL;
//	str = GetMemory();
//	strcpy(str, "hello world");
//	printf(str);
//
//	free(str);
//	str = NULL;
//}
//改正2
//void GetMemory(char** p)
//{
//	*p = (char*)malloc(100);
//}
//void Test(void)
//{
//	char* str = NULL;
//	GetMemory(&str);
//	strcpy(str, "hello world");
//	printf(str);
//	free(str);
//	str = NULL;
//}
//void Test(void)
//{
//	char* str = NULL;
//	GetMemory(str);
//	strcpy(str, "hello world");//程序在执行这一步时，就会崩溃
//	//也会造成内存泄露
//	printf(str);
//}
//int main()
//{
//	Test();
//
//	return 0;
//}


//void GetMemory(char* p)
//{
//	p = (char*)malloc(100);
//}
//void Test(void)
//{
//	char* str = NULL;
//	GetMemory(str);
//	strcpy(str, "hello world");//程序在执行这一步时，就会崩溃
//	//也会造成内存泄露
//	printf(str);//printf这样打印没有问题
//}
//int main()
//{
//	Test();
//	printf("hehe\n");//char* p = "hehe"
//	return 0;
//}


//笔试题2
//char* GetMemory()
//{
//	//返回栈空间地址的问题
//	char p[] = "hello world";
//	return p;
//}
//void Test(void)
//{
//	char* str = NULL;
//	str = GetMemory();//野指针
//	printf(str);//打印随机值
//}
//int main()
//{
//	Test();
//
//
//	return 0;
//}
// //这个没有问题
//int Add(int x, int y)
//{
//	int z = 0;
//	z = x + y;
//	return z;
//}
//int main()
//{
//	int r  = Add(3,5);
//	printf("%d\n", r);
//	return 0;
//}

//返回栈空间地址的问题
//int* text()
//{
//	int a = 10;
//	return &a;
//	//返回后，就会还给操作系统
//}
//int main()
//{
//	int* p = text();
//	//返回局部变量或临时变量的地址: a
//	printf("hehe\n");
//	printf("%d\n", *p);//依然是非法访问
//	return 0;
//}


//笔试题3
//void GetMemory(char** p, int num)
//{
//	*p = (char*)malloc(num);
//	
//}
//void Test(void)
//{
//	char* str = NULL;
//	GetMemory(&str, 100);
//	strcpy(str, "hello");
//	printf(str);
//	free(str);
//	str = NULL;
//}
//int main()
//{
//	Test();
//
//	return 0;
//}


//笔试题4
//void Test(void)
//{
//	char* str = (char*)malloc(100);
//	strcpy(str, "hello");
//	free(str);
//	//str已经是野指针了
//	str = NULL;//解决方法
//	if (str != NULL)
//	{
//		strcpy(str, "world");//非法访问
//		printf(str);
//	}
//}
//int main()
//{
//	Test();
//
//	return 0;
//}




//柔性数组
//C99 中，结构中的最后⼀个元素允许是未知⼤⼩的数组，这就叫做『柔性数组』成员
//  在结构体中的数组
// 结合动态内存管理使用的
//struct st_type
//{
//	int i;
//	int a[0];//柔性数组成员，如果编译器不支持的话写成 int a[];
//
//
//};

//柔性数组的特点
//• 结构中的柔性数组成员前⾯必须⾄少⼀个其他成员。
//• sizeof 返回的这种结构⼤⼩不包括柔性数组的内存。
//• 包含柔性数组成员的结构⽤malloc()函数进⾏内存的动态分配，并且分配的内存应该⼤于结构的⼤
//⼩，以适应柔性数组的预期⼤⼩。

//struct S1
//{
//	int n;
//	int arr[];//柔性数组
//};
//int main()
//{
//	//struct S s;//不会这样使用
//	// 会这样写
//	struct S1* ps = (struct S1*)malloc(sizeof(struct S1) + 5 * sizeof(int));
//	//                                                  这个就是柔性数组的大小
//	if (ps == NULL)
//	{
//		return 1;
//	}
//	//柔性数组赋值
//	ps->n = 100;
//	int i = 0;
//	for (i = 0; i < 5; i++) 
//	{
//		ps->arr[i] = i + 1;
//	}
//	
//
//	//printf("%zd\n", sizeof(struct S));//不包含柔性数组
//
//	//如果数组不够可以realloc重新分配就可以了
//	struct S* tmp = (struct S1*)realloc(ps,sizeof(struct S1) + 40);
//
//	if (tmp == NULL)
//	{
//		perror("realloc");
//		return 1;
//	}
//	ps = tmp;
//	for (i = 5; i < 10; i++)
//	{
//		ps->arr[i] = i + 1;
//	}
//
//	for (int i = 0; i < 10; i++)
//	{
//		printf("%d ", ps->arr[i]);
//	}
//
//	//释放
//	free(ps);
//	ps = NULL;
//
//	return 0;
//}
// 1. 所有的空间都是在堆上创建的
// 2. 所有的内存都是可以动态分配的

//struct S2
//{
//	int n;
//	int* arr;
//};
//int main()
//{
//	struct S2* ps = (struct S2*)malloc(sizeof(struct S2));
//
//	if (ps == NULL)
//	{
//		perror("malloc-1");
//		return 1;
//	}
//
//	ps->n = 100;
//	ps->arr = (int*)malloc(5 * sizeof(int));
//	if (ps->arr == NULL)
//	{
//		perror("malloc-2");
//		return 1;
//	}
//	//使用
//	int i = 0;
//	for (i = 0; i < 5; i++)
//	{
//		ps->arr[i] = i + 1;
//	}
//
//	int* ptr = (int*)realloc(ps->arr, 10 * sizeof(int));
//	if (ptr == NULL)
//	{
//		perror("realloc");
//		return 1;
//	}
//	else {
//		ps->arr = ptr;
//	}
//
//	for (i = 5; i < 10; i++)
//	{
//		ps->arr[i] = i + 1;
//	}
//
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", ps->arr[i]);
//	}
//	//释放
//	free(ps->arr);
//	ps->arr = NULL;
//	free(ps);
//	ps = NULL;
//
//	return 0;
//}


//使用柔性数组的话(S1和S2相比)

//第⼀个好处是：⽅便内存释放

//第⼆个好处是：这样有利于访问速度，也有益于减少内存碎⽚。






//文件
//1.为什么使⽤⽂件？
//将数据进⾏持久化的保存，我们可以使⽤⽂件。
//2.什么是⽂件？
//磁盘（硬盘）上的⽂件是⽂件.可以分为程序⽂件、数据⽂件（从⽂件功能的⻆度来分类的）。
int main()
{
	int a = 0;
	int b = 0;
	//创建到内存的
	scanf("%d %d", &a, &b);
	int c = a + b;
	printf("%d\n", c);

	return 0;
}
//程序一旦结束内存就会返回操作系统




